// 推荐阅读： https://segmentfault.com/a/1190000038607869

// 线段上距离点P最近的一个点
export function getNearestCoord(point, lines) {
  let d,
    res = { dist: Infinity };
  if (!(Array.isArray(lines[0]) && Array.isArray(lines[0][0]))) {
    lines = [lines];
  }
  lines.forEach(function (coords) {
    for (let i = 0; i < coords.length; i++) {
      d = dist2d(point, coords[i]);
      if (d < res.dist) {
        res.dist = d;
        res.index = i;
        res.point = coords[i];
      }
    }
  });

  return res.point ? res : null;
}
//   getNearestCoord([2.2, 3.1], [[1, 1], [2, 3], [3, 3], [4, 2], [2, 0]])
// {dist: 0.5099019513592785, index: 1, point: [2, 3]}

//点到点的距离
export function dist2d(coord1, coord2) {
  let dx = coord1[0] - coord2[0];
  let dy = coord1[1] - coord2[1];
  return Math.sqrt(dx * dx + dy * dy);
}

/* 
* 点P到线段AB的最短距离
* 使用矢量算法，计算线AP在线段AB方向上的投影，当需要计算的数据量很大时，这种方式优势明显
* 特殊情况如点在线段上、点在端点、点在线段延长线上等等的情况全部适用于此公式，只是作为特殊情况出现，无需另作讨论。这也是矢量算法思想的优势所在。
* 函数返回值：point 投影坐标  dist 点P到投影距离  type 垂足位置，不为0表示垂足在线段外
*/
export function pointToSegmentDist(point, point1, point2){
    let x = point[0], x1 = point1[0], x2 = point2[0]
    let y = point[1], y1 = point1[1], y2 = point2[1]
  
    //线段AB 为一个点
    if(x1 == x2 && y1 == y2) return {
      type: 0,
      point: point1,
      dist: 0
    }
  
    let cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
    //let r = cross / d2
    //r < 0 点P的垂足在线段AB外，且点P距离线段AB最近的点为A
    //r = 0 点P的垂足和点P距离线段AB最近的点为A
    if (cross <= 0) return {
      type: 1,
      point: point1,
      dist: Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1))
    };
      
    let d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
    //r > 1 点P的垂足在线段AB外，且点P距离线段AB最近的点为B
    //r = 1 点P的垂足和点P距离线段AB最近的点为B
    if (cross >= d2) return {
      type: 2,
      point: point2,
      dist: Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2))
    };
      
    let r = cross / d2;
    let px = x1 + (x2 - x1) * r;
    let py = y1 + (y2 - y1) * r;
    return {
      type: 0,
      point: [px, py],
      dist: Math.sqrt((x - px) * (x - px) + (py - y) * (py - y))
    };
  }
//   pointToSegmentDist([1, 3], [0, 1], [3, 1]); 
  //{ dist: 2, point: [1, 1], type: 0 }